﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using WCBG.ToolsForUnity.Tools;
using WCBG.ToolsForUnity.Extension;


/// <summary>
/// 找积木
/// </summary>
public class GeometryFindToyBricksPart : StudyGeometryBasePart
{


    private const string trainHeadPath = StudyPath.geometry_train_head;
    private const string trainNodePath = StudyPath.geometry_train_node;
    private const float HINT_INTERVAL_TIME = 3f;


    private bool isHint;
    private float addTime;

    private EGeometryEnum m_geometryType;
    private GeometryTrainHeadActor m_TrainHeadActor;
    private GeometryTrainNodeActor m_TrainNodeActor;
    private GameAudioSource m_currentAudio;
    //private GameAudioSource m_trainLoopAudio;
    private Transform m_geometryFallPoint;
    private Transform m_trainHeadPoint;
    private Transform m_trainNodePoint;
    private GameObject m_currentEffect;

    private List<Transform> m_geometryStartPointList = new List<Transform>();
    private List<Transform> m_geometryEndPointList = new List<Transform>();
    private List<GeometryActor> m_selectActorList = new List<GeometryActor>();
    private List<GeometryActor> m_hintActorList = new List<GeometryActor>();
    private List<Vector3> m_trainMoveOutPath = new List<Vector3>();
    private List<Vector3> m_trainMoveInPath = new List<Vector3>();

    protected override void OnPartStart(params object[] paramArray)
    {
        base.OnPartStart(paramArray);

        SetScene(paramArray[0] as Transform);
        m_partIndex = (int)paramArray[1];

        //Debug.LogError(m_partIndex);
        bLockInput = true;
        addTime = 0;
        isHint = false;
        m_geometryType = GetGeometryType(m_partIndex + 1);
        InitializeGeometryPoints();
        CreateTrain();
        CreateRandomGeometry();

        if (m_partIndex == 0)
        {
            this.PlayActionAudioEx(ActionAudioName.t_2006, () =>
            {
                MoveTrainIn(() =>
                {
                    PlayHintAudio(() => {
                        bLockInput = false;
                    });
                });
            });
        }
        else
        {
            MoveTrainIn(() =>
            {
                PlayHintAudio(() =>
                {
                    bLockInput = false;
                });
            });
        }

        MedalWindow.Instance.ShowXunzhang(m_partIndex, false, MedalWindow.EXZCountEnum.Six);

        RefreshShadowProjecter();
    }

    protected override void OnPartUpdate()
    {
        base.OnPartUpdate();

        if (bLockInput)
            return;

        if (Input.anyKeyDown)
        {
            isHint = false;
            addTime = 0;
        }

        addTime += Time.deltaTime;
        if (isHint)
        {
            if (addTime > 1)
            {
                addTime = 0;
                OnHintAnimation();
            }
        }
        else
        {
            if (addTime > HINT_INTERVAL_TIME)
            {
                addTime = 0;
                isHint = true;
                OnHintAnimation();
            }
        }
    }

    protected override void OnPartExit()
    {
        base.OnPartExit();

        m_geometryStartPointList.Clear();
        m_geometryEndPointList.Clear();
        m_selectActorList.Clear();
        m_trainMoveOutPath.Clear();
        m_trainMoveInPath.Clear();
        m_hintActorList.Clear();

        addTime = 0;
        isHint = false;
    }

    protected override void OnMouseDown()
    {
        base.OnMouseDown();

        if (bLockInput)
            return;

        Transform target = FTools.GetRaycastHitTargetByMousePoint();
        if (target == null)
            return;

        GeometryActor actor = target.GetComponent<GeometryActor>();
        if (actor == null)
        {
            return;
        }

        if (actor.geometryType == m_geometryType)
        {
            actor.EnableCollision(false);
            actor.EnableAnimator(false);
            SelectActor(actor);
        }
        else
        {
            actor.CrossFade(GeometryActor.AnimatorNameEnum.Shake, 0.01f);
        }

        //if (m_currentAudio != null)
        //{
        //    m_currentAudio.Stop();
        //}
        m_currentAudio = actor.PlayGeometryActorAudio();
    }


    // 跳动提示
    private void OnHintAnimation()
    {
        if (m_hintActorList.Count > 0)
        {
            GeometryActor actor = m_hintActorList[Random.Range(0, m_hintActorList.Count)];
            actor.CrossFade(GeometryActor.AnimatorNameEnum.Shake, 0.01f);
        }
    }

    private void OnTrainMoveComplete()
    {
        OnPartComplete();
    }

    private void SelectActor(GeometryActor actor)
    {
        float time = 0.5f;
        actor.transform.DOMove(m_geometryFallPoint.position, time).SetEase(Ease.InQuad);
        actor.transform.DOScale(m_geometryFallPoint.localScale, time).SetEase(Ease.InQuad);
        this.PlayAudioEx(StudyAudioName.t_21021);
        m_hintActorList.Remove(actor);

        AddTimer(time + 0.2f, () => {

            float dropTime = 0.5f;
            Transform moveTo = GetEndPoint(m_selectActorList.Count);
            actor.transform.DOMove(moveTo.position, dropTime).SetEase(Ease.InQuad);
            actor.transform.DOScale(moveTo.localScale, dropTime).SetEase(Ease.InQuad);
            actor.transform.DORotateQuaternion(Quaternion.identity, dropTime).SetEase(Ease.InQuad);
            actor.transform.SetParent(m_TrainNodeActor.transform);
            m_selectActorList.Add(actor);
            AddTimer(dropTime, () =>
            {
                this.PlayAudioEx(StudyAudioName.t_21016);
            });

            if (m_selectActorList.Count > 4)
            {
                AddTimer(dropTime, () =>
                {
                    MoveTrain();
                });
            }

        });
    }

    private void MoveTrain()
    {
        if (m_currentEffect != null)
        {
            m_currentEffect.SetActive(false);
        }

        m_TrainHeadActor.CrossFade(GeometryTrainHeadActor.AnimatorNameEnum.Zoom, 0.01f);
        m_TrainNodeActor.CrossFade(GeometryTrainNodeActor.AnimatorNameEnum.UpAndDown, 0.01f);

        GameAudioSource audio = this.PlayAudioEx(StudyAudioName.t_21013); 
       
        AddTimer(2.5f, () =>
        {

            float moveTime = 3;
            float headDis = GetPathDistance(m_trainMoveOutPath.ToArray()) + Vector3.Distance(m_trainMoveOutPath[0], m_TrainHeadActor.transform.position);
            float nodeDis = GetPathDistance(m_trainMoveOutPath.ToArray()) + Vector3.Distance(m_trainMoveOutPath[0], m_TrainNodeActor.transform.position);
            m_TrainHeadActor.transform.DOPath(m_trainMoveOutPath.ToArray(), moveTime, PathType.CatmullRom, PathMode.Full3D).SetEase(Ease.Linear).SetLookAt(0.001f);
            m_TrainNodeActor.transform.DOPath(m_trainMoveOutPath.ToArray(), nodeDis / (headDis / moveTime), PathType.CatmullRom, PathMode.Full3D).SetEase(Ease.Linear).SetLookAt(0.001f);

            m_TrainHeadActor.CrossFade(GeometryTrainHeadActor.AnimatorNameEnum.Move, 0.01f);
            m_TrainNodeActor.CrossFade(GeometryTrainNodeActor.AnimatorNameEnum.Move, 0.01f);

            GameAudioSource audio1 = this.PlayAudioEx(StudyAudioName.t_21014);
            m_TrainHeadActor.PlayEffect(StudyPath.math_traineffect_out_big);

            AddTimer(moveTime, () =>
            {
                audio1.Stop();
                
                //this.PlayAudioEx(StudyAudioName.t_21025);
                MedalWindow.Instance.ShowXunzhang(m_partIndex + 1, true, MedalWindow.EXZCountEnum.Six,()=> {

                    PlayHeartenAudio(() =>
                    {
                        OnTrainMoveComplete();
                    });
                    
                });
            });

        });


    }

    private void PlayHeartenAudio(System.Action callback)
    {
        switch (m_partIndex)
        {
            case 0:
            case 1:
            case 3:
            case 4:
                if (callback != null)
                    callback();
                break;
            case 2:
                this.PlayActionAudioEx(ActionAudioName.t_2007, callback);
                break;
            case 5:
                if (callback != null)
                    callback();
                break;
        }
    }

    private void PlayHintAudio(System.Action callback)
    {
        if (callback != null)
            callback();
        //string audioName = StudyAudioName.talk_403040402_x + (m_partIndex + 1);
        //PlayerAnimationController.Instance.PlayAnimaton(PlayerAnimationController.PlayerAnimationEnum.LeftBottomToHalf, LediActor.AnimatorNameEnum.happy_p, StudyPath.study_geometry_audio_basepath + audioName, () =>
        //{
        //    if (callback != null)
        //        callback();
        //});
    }

    private Transform GetEndPoint(int index)
    {
        return m_geometryEndPointList[index];
    }

    private void InitializeGeometryPoints()
    {
        Transform Geometry_FindBricks = Scene.Find(StudyPath.geometry_track_findbricks.GetPathName());
        if (Geometry_FindBricks == null)
        {
            Debug.LogError("Get obj error! ");
            return;
        }
        m_geometryFallPoint = Geometry_FindBricks.Find("geometry_fall_point");
        m_trainHeadPoint = Geometry_FindBricks.Find("train_movein_path/train_head_point");
        m_trainNodePoint = Geometry_FindBricks.Find("train_movein_path/train_node_point");

        Transform startParent = Geometry_FindBricks.Find("geometry_startpoint_parent");
        m_geometryStartPointList.Clear();
        for (int i = 0, max = startParent.childCount; i < max; i++)
        {
            m_geometryStartPointList.Add(startParent.GetChild(i));
        }

        Transform endParent = Geometry_FindBricks.Find("geometry_endpoint_parent");
        m_geometryEndPointList.Clear();
        for (int i = 0, max = endParent.childCount; i < max; i++)
        {
            m_geometryEndPointList.Add(endParent.GetChild(i));
        }

        Transform pathParent = Geometry_FindBricks.Find("train_moveout_path");
        for (int i = 0; i < pathParent.childCount; i++)
        {
            m_trainMoveOutPath.Add(pathParent.GetChild(i).position);
        }
        Transform pathInParent = Geometry_FindBricks.Find("train_movein_path");
        for (int i = 0; i < pathInParent.childCount; i++)
        {
            m_trainMoveInPath.Add(pathInParent.GetChild(i).position);
        }

    }

    private void CreateTrain()
    {
        m_TrainHeadActor = Instantiate(trainHeadPath, true, true).AddComponentEx<GeometryTrainHeadActor>();
        m_TrainNodeActor = Instantiate(trainNodePath, true, true).AddComponentEx<GeometryTrainNodeActor>();

        m_TrainHeadActor.Initialize(m_geometryType);

        m_TrainHeadActor.transform.SetTransformFormTarget(m_trainHeadPoint);
        m_TrainNodeActor.transform.SetTransformFormTarget(m_trainNodePoint);
        m_TrainHeadActor.transform.position = m_trainMoveInPath[1];
        m_TrainNodeActor.transform.position = m_trainMoveInPath[0];
    }

    private void MoveTrainIn(System.Action callback = null)
    {
        GameAudioSource audio = this.PlayAudioEx(StudyAudioName.t_21013); // PlayGeometryAudio(StudyAudioName.sound_603020101);

        AddTimer(audio.Length, () => {
            
            float moveTime = 3;
            List<Vector3> headPath = GetTrainMoveInPath(1, 6);
            m_TrainHeadActor.transform.position = headPath[0];
            m_TrainHeadActor.transform.DOPath(headPath.ToArray(), moveTime, PathType.CatmullRom, PathMode.Full3D).SetEase(Ease.Linear).SetLookAt(0.001f);
            List<Vector3> nodePath = GetTrainMoveInPath(0, 5);
            m_TrainNodeActor.transform.position = nodePath[0];
            m_TrainNodeActor.transform.DOPath(nodePath.ToArray(), moveTime, PathType.CatmullRom, PathMode.Full3D).SetEase(Ease.Linear).SetLookAt(0.001f);

            m_TrainHeadActor.CrossFade(GeometryTrainHeadActor.AnimatorNameEnum.Move, 0.01f);
            m_TrainNodeActor.CrossFade(GeometryTrainNodeActor.AnimatorNameEnum.Move, 0.01f);
            m_TrainHeadActor.PlayEffect(StudyPath.math_traineffect_out_big);
            GameAudioSource audio1 = this.PlayAudioEx(StudyAudioName.t_21014, true); // PlayGeometryAudio(StudyAudioName.sound_603020201, true);

            AddTimer(moveTime, () =>
            {
                audio1.Stop();
                m_TrainHeadActor.ClearEffect();
                m_TrainHeadActor.CrossFade(GeometryTrainHeadActor.AnimatorNameEnum.Static, 0.01f);
                m_TrainNodeActor.CrossFade(GeometryTrainNodeActor.AnimatorNameEnum.Static, 0.01f);
                GameAudioSource audio2 = this.PlayAudioEx(StudyAudioName.t_21015); // PlayGeometryAudio(StudyAudioName.sound_603020202);

                //m_currentEffect = m_TrainHeadActor.PlayEffect(StudyPath.math_traineffect_hint);
                if (callback != null)
                    callback();
            });

        });
    }

    private void CreateRandomGeometry()
    {
        List<int> createIndex = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

        int rectangleIndex = 0;
        // 先创建5个正确答案
        for (int i = 0; i < 5; i++)
        {
            GeometryActor actor = CreateGeometry(m_geometryType, i);
            int randomIndex = Random.Range(0, createIndex.Count);
            //Debug.LogError(createIndex[randomIndex]);
            Transform point = m_geometryStartPointList[createIndex[randomIndex]];
            actor.transform.SetTransformFormTarget(point);
            actor.transform.SetScale(Random.Range(0.7f, 1));

            // 如果是长方形，随机竖两个
            if (m_geometryType == EGeometryEnum.Rectangle && rectangleIndex < 2)
            {
                actor.transform.rotation = Quaternion.Euler(0, 90, 0);
                rectangleIndex++;
            }
            else if (m_geometryType == EGeometryEnum.Triangle && i == 0)
            {
                actor.transform.rotation = Quaternion.Euler(0, 180, 0);
            }

            createIndex.RemoveAt(randomIndex);
            m_hintActorList.Add(actor);
        }

        List<int> typeList = new List<int>() { 0, 1, 2, 3, 4, 5 };
        typeList.Remove((int)m_geometryType);

        for (int i = 0; i < 5; i++)
        {
            int randomTypeIndex = Random.Range(0, typeList.Count);
            EGeometryEnum randomType = (EGeometryEnum)typeList[randomTypeIndex];
            typeList.RemoveAt(randomTypeIndex);
            GeometryActor actor = CreateGeometry(randomType, Random.Range(0, 5));
            actor.EnableAnimator(true);
            int randomIndex = Random.Range(0, createIndex.Count);

            //Debug.LogError(createIndex[randomIndex]);
            Transform point = m_geometryStartPointList[createIndex[randomIndex]];
            actor.transform.SetTransformFormTarget(point);
            actor.transform.SetScale(Random.Range(0.7f, 1));

            createIndex.RemoveAt(randomIndex);
        }

    }

    // 每种类型有5个
    private GeometryActor CreateGeometry(EGeometryEnum type, int index)
    {
        GeometryActor actor = Instantiate(GetGeometryAssetPath(type, index), true, true).AddComponentEx<GeometryActor>();
        actor.Initialize(type);
        return actor;
    }

    private string GetGeometryAssetPath(EGeometryEnum type, int index)
    {
        List<string> pathList = new List<string>();
        switch (type)
        {
            case EGeometryEnum.Circle:
                pathList.Add(StudyPath.geometry_circle_1);
                pathList.Add(StudyPath.geometry_circle_2);
                pathList.Add(StudyPath.geometry_circle_3);
                pathList.Add(StudyPath.geometry_circle_4);
                pathList.Add(StudyPath.geometry_circle_5);
                break;
            case EGeometryEnum.Square:
                pathList.Add(StudyPath.geometry_square_1);
                pathList.Add(StudyPath.geometry_square_2);
                pathList.Add(StudyPath.geometry_square_3);
                pathList.Add(StudyPath.geometry_square_4);
                pathList.Add(StudyPath.geometry_square_5);
                break;
            case EGeometryEnum.Triangle:
                pathList.Add(StudyPath.geometry_triangle_1);
                pathList.Add(StudyPath.geometry_triangle_2);
                pathList.Add(StudyPath.geometry_isoscelesTriangle_1);
                pathList.Add(StudyPath.geometry_rightTriangle_1);
                pathList.Add(StudyPath.geometry_rightTriangle_2);
                break;
            case EGeometryEnum.Rectangle:
                pathList.Add(StudyPath.geometry_rectangle_1);
                pathList.Add(StudyPath.geometry_rectangle_2);
                pathList.Add(StudyPath.geometry_rectangle_3);
                pathList.Add(StudyPath.geometry_rectangle_4);
                pathList.Add(StudyPath.geometry_rectangle_5);
                break;
            case EGeometryEnum.Trapezoid:
                pathList.Add(StudyPath.geometry_isoscelesTrapezoid_1);
                pathList.Add(StudyPath.geometry_trapezoid_1);
                pathList.Add(StudyPath.geometry_trapezoid_2);
                pathList.Add(StudyPath.geometry_trapezoid_4);
                pathList.Add(StudyPath.geometry_trapezoid_5);
                break;
            case EGeometryEnum.Ellipse:
                pathList.Add(StudyPath.geometry_ellipse_1);
                pathList.Add(StudyPath.geometry_ellipse_2);
                pathList.Add(StudyPath.geometry_ellipse_3);
                pathList.Add(StudyPath.geometry_ellipse_4);
                pathList.Add(StudyPath.geometry_ellipse_5);
                break;
        }
        return pathList[index];
    }

    private EGeometryEnum GetGeometryType(int index)
    {
        switch (index)
        {
            case 1:
                return EGeometryEnum.Circle;
            case 2:
                return EGeometryEnum.Square;
            case 3:
                return EGeometryEnum.Triangle;
            case 4:
                return EGeometryEnum.Rectangle;
            case 5:
                return EGeometryEnum.Trapezoid;
            case 6:
                return EGeometryEnum.Ellipse;
            default:
                return EGeometryEnum.Circle;
        }
    }

    private float GetPathDistance(Vector3[] path)
    {
        float dis = 0;
        for (int i = 0; i < path.Length - 1; i++)
        {
            dis += Vector3.Distance(path[i], path[i + 1]);
        }
        return dis;
    }

    private List<Vector3> GetTrainMoveInPath(int start, int end)
    {
        List<Vector3> list = new List<Vector3>();
        for (int i = start, j = end + 1; i < j; i++)
        {
            list.Add(m_trainMoveInPath[i]);
        }
        return list;
    }

}
